home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 June / PersonalComputerWorld-June2009-CoverdiscCD.iso / Software / Freeware / Firebug 1.3.3 / firebug-1.3.3-fx.xpi / content / firebug / console.js < prev    next >
Encoding:
JavaScript  |  2009-02-19  |  20.2 KB  |  681 lines

  1. /* See license.txt for terms of usage */
  2.  
  3. FBL.ns(function() { with (FBL) {
  4.  
  5. const Cc = Components.classes;
  6. const Ci = Components.interfaces;
  7. const nsIPrefBranch2 = Ci.nsIPrefBranch2;
  8. const PrefService = Cc["@mozilla.org/preferences-service;1"];
  9. const prefs = PrefService.getService(nsIPrefBranch2);
  10.  
  11. // ************************************************************************************************
  12.  
  13. var listeners = [];
  14. var maxQueueRequests = 500;
  15.  
  16. // ************************************************************************************************
  17.  
  18. Firebug.ConsoleBase =
  19. {
  20.     log: function(object, context, className, rep, noThrottle, sourceLink)
  21.     {
  22.         dispatch(listeners,"log",[context, object, className, sourceLink]);
  23.         return this.logRow(appendObject, object, context, className, rep, sourceLink, noThrottle);
  24.     },
  25.  
  26.     logFormatted: function(objects, context, className, noThrottle, sourceLink)
  27.     {
  28.         dispatch(listeners,"logFormatted",[context, objects, className, sourceLink]);
  29.         return this.logRow(appendFormatted, objects, context, className, null, sourceLink, noThrottle);
  30.     },
  31.  
  32.     openGroup: function(objects, context, className, rep, noThrottle, sourceLink, noPush)
  33.     {
  34.         return this.logRow(appendOpenGroup, objects, context, className, rep, sourceLink, noThrottle);
  35.     },
  36.  
  37.     closeGroup: function(context, noThrottle)
  38.     {
  39.         return this.logRow(appendCloseGroup, null, context, null, null, null, noThrottle, true);
  40.     },
  41.  
  42.     logRow: function(appender, objects, context, className, rep, sourceLink, noThrottle, noRow)
  43.     {
  44.         if (noThrottle || !context)
  45.         {
  46.             var panel = this.getPanel(context);
  47.             if (panel)
  48.             {
  49.                 var row = panel.append(appender, objects, className, rep, sourceLink, noRow);
  50.  
  51.                 var container = panel.panelNode;
  52.                 var template = Firebug.NetMonitor.NetLimit;
  53.  
  54.                 while (container.childNodes.length > maxQueueRequests + 1)
  55.                 {
  56.                     container.removeChild(container.firstChild.nextSibling);
  57.                     panel.limit.limitInfo.totalCount++;
  58.                     template.updateCounter(panel.limit);
  59.                 }
  60.  
  61.                 return row;
  62.             }
  63.         }
  64.         else
  65.         {
  66.             var args = [appender, objects, context, className, rep, sourceLink, true, noRow];
  67.             context.throttle(this.logRow, this, args);
  68.         }
  69.     },
  70.  
  71.     appendFormatted: function(args, row, context)
  72.     {
  73.         if (!context)
  74.             context = FirebugContext;
  75.  
  76.         var panel = this.getPanel(context);
  77.         panel.appendFormatted(args, row);
  78.     },
  79.  
  80.     clear: function(context)
  81.     {
  82.         if (!context)
  83.             context = FirebugContext;
  84.  
  85.         Firebug.Errors.clear(context);
  86.  
  87.         var panel = this.getPanel(context, true);
  88.         if (panel)
  89.             panel.clear();
  90.     },
  91.  
  92.     // Override to direct output to your panel
  93.     getPanel: function(context, noCreate)
  94.     {
  95.         return context.getPanel("console", noCreate);
  96.     },
  97.  
  98.     addListener: function(listener)
  99.     {
  100.         listeners.push(listener);
  101.     },
  102.  
  103.     removeListener: function(listener)
  104.     {
  105.         remove(listeners, listener);
  106.     },
  107.  
  108.  
  109. }
  110.  
  111. var ActivableConsole = extend(Firebug.ActivableModule, Firebug.ConsoleBase);
  112.  
  113. Firebug.Console = extend(ActivableConsole,
  114. {
  115.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  116.     // extends Module
  117.  
  118.     showPanel: function(browser, panel)
  119.     {
  120.     },
  121.  
  122.     getFirebugConsoleElement: function(context, win)
  123.     {
  124.         var element = win.document.getElementById("_firebugConsole");
  125.         if (!element)
  126.         {
  127.             var elementForcer = "var r=null; try { r = window._getFirebugConsoleElement();}catch(exc){r=exc;} r;";  // we could just add the elements here
  128.             
  129.             if (context.stopped)
  130.                 Firebug.Console.injector.evaluateConsoleScript(context);  // todo evaluate consoleForcer on stack
  131.             else
  132.                 var r = Firebug.CommandLine.evaluateInSandbox(elementForcer, context, null, win);
  133.             
  134.             var element = win.document.getElementById("_firebugConsole");
  135.             if (!element) // elementForce fails
  136.             {
  137.                 Firebug.Console.logFormatted(["Firebug cannot find _firebugConsole element", r, win], context, "error", true);
  138.             }
  139.         }
  140.         
  141.         return element;
  142.     },
  143.     
  144.     isNeededGetReady: function(context, win) 
  145.     {
  146.         if (win)
  147.             return this.injector.attachIfNeeded(context, win);
  148.         else
  149.         {
  150.             for (var i = 0; i < context.windows.length; i++)
  151.                 this.injector.attachIfNeeded(context, context.windows[i]);
  152.             return this.injector.attachIfNeeded(context, context.window);
  153.         }
  154.     },
  155.     
  156.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  157.     // extends ActivableModule
  158.     initialize: function()
  159.     {
  160.         this.panelName = "console";
  161.         this.description = $STR("console.modulemanager.description");
  162.  
  163.         Firebug.ActivableModule.initialize.apply(this, arguments);
  164.     },
  165.  
  166.     initContext: function(context)
  167.     {
  168.         Firebug.ActivableModule.initContext.apply(this, arguments);
  169.  
  170.         // Create limit row. This row is the first in the list of entries
  171.         // and initially hidden. It's displayed as soon as the number of
  172.         // entries reache the limit.
  173.         var panel = context.getPanel(this.panelName);
  174.         var row = panel.createRow("limitRow");
  175.  
  176.         var limitInfo = {
  177.             totalCount: 0,
  178.             limitPrefsTitle: $STRF("LimitPrefsTitle", [Firebug.prefDomain+".console.logLimit"])
  179.         };
  180.  
  181.         var netLimitRep = Firebug.NetMonitor.NetLimit;
  182.         var nodes = netLimitRep.createTable(row, limitInfo);
  183.  
  184.         panel.limit = nodes[1];
  185.  
  186.         var container = panel.panelNode;
  187.         container.insertBefore(nodes[0], container.firstChild);
  188.     },
  189. /*
  190.     watchWindow: function(context, win)
  191.     {
  192.         if (this.isEnabled(context))
  193.         {
  194.             this.injector.attachConsoleInjector(context, win);
  195.             this.injector.addConsoleListener(context, win); 
  196.         }
  197.  
  198.     },
  199. */
  200.     showContext: function(browser, context)
  201.     {
  202.         if (browser)
  203.             browser.chrome.setGlobalAttribute("cmd_clearConsole", "disabled", !context);
  204.  
  205.         Firebug.ActivableModule.showContext.apply(this, arguments);
  206.     },
  207.  
  208.     // -----------------------------------------------------------------------------------------------------
  209.  
  210.     onFirstPanelActivate: function(context, init)
  211.     {
  212.         Firebug.Errors.startObserving();
  213.         Firebug.Debugger.registerDebugger(); // 1.3.1 we inject the console during JS compiles so we need jsd
  214.     },
  215.  
  216.     onPanelActivate: function(context, init, panelName)
  217.     {
  218.         if (panelName != this.panelName)  // no cross panel work needed
  219.             return;
  220.  
  221.         if (!init)
  222.             context.window.location.reload();
  223.     },
  224.  
  225.     onLastPanelDeactivate: function(context, destroy)
  226.     {
  227.         Firebug.Errors.stopObserving();
  228.         Firebug.Debugger.unregisterDebugger(); // 1.3.1 we inject the console during JS compiles so we need jsd, now we are done with it
  229.     },
  230.  
  231.     onSuspendFirebug: function(context)
  232.     {
  233.         Firebug.Errors.stopObserving();  // safe for multiple calls
  234.     },
  235.  
  236.     onResumeFirebug: function(context)
  237.     {
  238.         if (this.isEnabled(context))
  239.             Firebug.Errors.startObserving(); // safe for multiple calls
  240.     },
  241.     // ----------------------------------------------------------------------------------------------------
  242.  
  243.     logRow: function(appender, objects, context, className, rep, sourceLink, noThrottle, noRow)
  244.     {
  245.         if (!context)
  246.             context = FirebugContext;
  247.  
  248.         if (this.isEnabled(context))
  249.             return Firebug.ConsoleBase.logRow.apply(this, arguments);
  250.     }
  251. });
  252.  
  253. Firebug.ConsoleListener =
  254. {
  255.     log: function(context, object, className, sourceLink)
  256.     {
  257.     },
  258.  
  259.     logFormatted: function(context, objects, className, sourceLink)
  260.     {
  261.     }
  262. };
  263.  
  264. // ************************************************************************************************
  265.  
  266. Firebug.ConsolePanel = function () {} // XXjjb attach Firebug so this panel can be extended.
  267.  
  268. Firebug.ConsolePanel.prototype = extend(Firebug.AblePanel,
  269. {
  270.     wasScrolledToBottom: true,
  271.     messageCount: 0,
  272.     lastLogTime: 0,
  273.     groups: null,
  274.     limit: null,
  275.  
  276.     append: function(appender, objects, className, rep, sourceLink, noRow)
  277.     {
  278.         var container = this.getTopContainer();
  279.  
  280.         if (noRow)
  281.         {
  282.             appender.apply(this, [objects]);
  283.         }
  284.         else
  285.         {
  286.             var scrolledToBottom = isScrolledToBottom(this.panelNode);
  287.  
  288.             var row = this.createRow("logRow", className);
  289.             appender.apply(this, [objects, row, rep]);
  290.  
  291.             if (sourceLink)
  292.                 FirebugReps.SourceLink.tag.append({object: sourceLink}, row);
  293.  
  294.             container.appendChild(row);
  295.  
  296.             this.filterLogRow(row, scrolledToBottom);
  297.  
  298.             if (scrolledToBottom)
  299.                 scrollToBottom(this.panelNode);
  300.  
  301.             return row;
  302.         }
  303.     },
  304.  
  305.     clear: function()
  306.     {
  307.         if (this.panelNode)
  308.             clearNode(this.panelNode);
  309.     },
  310.  
  311.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  312.  
  313.     appendObject: function(object, row, rep)
  314.     {
  315.         if (!rep)
  316.             rep = Firebug.getRep(object);
  317.         return rep.tag.append({object: object}, row);
  318.     },
  319.  
  320.     appendFormatted: function(objects, row, rep)
  321.     {
  322.         if (!objects || !objects.length)
  323.             return;
  324.  
  325.         var format = objects[0];
  326.         var objIndex = 0;
  327.  
  328.         if (typeof(format) != "string")
  329.         {
  330.             format = "";
  331.             objIndex = -1;
  332.         }
  333.  
  334.         function logText(text)
  335.         {
  336.             var node = row.ownerDocument.createTextNode(text);
  337.             row.appendChild(node);
  338.         }
  339.  
  340.         var parts = parseFormat(format);
  341.         var trialIndex = objIndex;
  342.         for (var i= 0; i < parts.length; i++)
  343.         {
  344.             var part = parts[i];
  345.             if (part && typeof(part) == "object")
  346.             {
  347.                 if (++trialIndex > objects.length)  // then too few parameters for format, assume unformatted.
  348.                 {
  349.                     format = "";
  350.                     objIndex = -1;
  351.                     parts.length = 0;
  352.                     break;
  353.                 }
  354.             }
  355.  
  356.         }
  357.         for (var i = 0; i < parts.length; ++i)
  358.         {
  359.             var part = parts[i];
  360.             if (part && typeof(part) == "object")
  361.             {
  362.                 var object = objects[++objIndex];
  363.                 this.appendObject(object, row, part.rep);
  364.             }
  365.             else
  366.                 FirebugReps.Text.tag.append({object: part}, row);
  367.         }
  368.  
  369.         for (var i = objIndex+1; i < objects.length; ++i)
  370.         {
  371.             logText(" ", row);
  372.             var object = objects[i];
  373.             if (typeof(object) == "string")
  374.                 FirebugReps.Text.tag.append({object: object}, row);
  375.             else
  376.                 this.appendObject(object, row);
  377.         }
  378.     },
  379.  
  380.     appendOpenGroup: function(objects, row, rep)
  381.     {
  382.         if (!this.groups)
  383.             this.groups = [];
  384.  
  385.         setClass(row, "logGroup");
  386.         setClass(row, "opened");
  387.  
  388.         var innerRow = this.createRow("logRow");
  389.         if (rep)
  390.             rep.tag.replace({"objects": objects}, innerRow);
  391.         else
  392.             this.appendFormatted(objects, innerRow, rep);
  393.         row.appendChild(innerRow);
  394.  
  395.         var groupBody = this.createRow("logGroupBody");
  396.         row.appendChild(groupBody);
  397.  
  398.         this.groups.push(groupBody);
  399.  
  400.         innerRow.addEventListener("mousedown", function(event)
  401.         {
  402.             if (isLeftClick(event))
  403.             {
  404.                 var groupRow = event.currentTarget.parentNode;
  405.                 if (hasClass(groupRow, "opened"))
  406.                     removeClass(groupRow, "opened");
  407.                 else
  408.                     setClass(groupRow, "opened");
  409.             }
  410.         }, false);
  411.     },
  412.  
  413.     appendCloseGroup: function(object, row, rep)
  414.     {
  415.         if (this.groups)
  416.             this.groups.pop();
  417.     },
  418.  
  419.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  420.     // extends Panel
  421.  
  422.     name: "console",
  423.     searchable: true,
  424.     editable: false,
  425.  
  426.     initialize: function()
  427.     {
  428.         Firebug.Panel.initialize.apply(this, arguments);
  429.  
  430.         // Initialize log limit and listen for changes.
  431.         this.updateMaxLimit();
  432.         prefs.addObserver(Firebug.prefDomain, this, false);
  433.     },
  434.  
  435.     shutdown: function() {
  436.         prefs.removeObserver(Firebug.prefDomain, this, false);
  437.     },
  438.  
  439.     show: function(state)
  440.     {
  441.         // The "enable/disable" button is always visible.
  442.         this.showToolbarButtons("fbConsoleButtons", true); // TODO, only enable/disable menu here
  443.                                                    /*@explore*/
  444.         // The default page with description and enable button is
  445.         // visible only if debugger is disabled.
  446.         var enabled = Firebug.Console.isEnabled(this.context);
  447.         if (enabled)
  448.         {
  449.             Firebug.ModuleManagerPage.hide(this);
  450.  
  451.             FirebugContext.chrome.$("fbCommandBox").collapsed = false;
  452.             if (Firebug.largeCommandLine)
  453.                 Firebug.CommandLine.setMultiLine(true);
  454.  
  455.             if (this.wasScrolledToBottom)
  456.                 scrollToBottom(this.panelNode);
  457.         }
  458.         else
  459.         {
  460.             Firebug.CommandLine.setMultiLine(false);
  461.             FirebugContext.chrome.$("fbCommandBox").collapsed = true;
  462.  
  463.             Firebug.ModuleManagerPage.show(this, Firebug.Console);
  464.         }
  465.     },
  466.  
  467.     hide: function()
  468.     {
  469.         this.showToolbarButtons("fbConsoleButtons", false);
  470.         this.wasScrolledToBottom = isScrolledToBottom(this.panelNode);
  471.     },
  472.  
  473.     getOptionsMenuItems: function()
  474.     {
  475.         return [
  476.             optionMenu("ShowJavaScriptErrors", "showJSErrors"),
  477.             optionMenu("ShowJavaScriptWarnings", "showJSWarnings"),
  478.             optionMenu("ShowCSSErrors", "showCSSErrors"),
  479.             optionMenu("ShowXMLErrors", "showXMLErrors"),
  480.             optionMenu("ShowXMLHttpRequests", "showXMLHttpRequests"),
  481.             optionMenu("ShowChromeErrors", "showChromeErrors"),
  482.             optionMenu("ShowChromeMessages", "showChromeMessages"),
  483.             optionMenu("ShowExternalErrors", "showExternalErrors"),
  484.             this.getShowStackTraceMenuItem(),
  485.             this.getStrictOptionMenuItem(),
  486.             "-",
  487.             optionMenu("LargeCommandLine", "largeCommandLine")
  488.         ];
  489.     },
  490.  
  491.     getShowStackTraceMenuItem: function()
  492.     {
  493.         var menuItem = serviceOptionMenu("ShowStackTrace", "showStackTrace");
  494.         if (FirebugContext && !Firebug.Debugger.isEnabled(FirebugContext))
  495.             menuItem.disabled = true;
  496.         return menuItem;
  497.     },
  498.  
  499.     getStrictOptionMenuItem: function()
  500.     {
  501.         var strictDomain = "javascript.options";
  502.         var strictName = "strict";
  503.         var strictValue = prefs.getBoolPref(strictDomain+"."+strictName);
  504.         return {label: "JavascriptOptionsStrict", type: "checkbox", checked: strictValue,
  505.             command: bindFixed(Firebug.setPref, Firebug, strictDomain, strictName, !strictValue) };
  506.     },
  507.  
  508.     search: function(text)
  509.     {
  510.         if (!text)
  511.             return;
  512.  
  513.         // Make previously visible nodes invisible again
  514.         if (this.matchSet)
  515.         {
  516.             for (var i in this.matchSet)
  517.                 removeClass(this.matchSet[i], "matched");
  518.         }
  519.  
  520.         this.matchSet = [];
  521.  
  522.         function findRow(node) { return getAncestorByClass(node, "logRow"); }
  523.         var search = new TextSearch(this.panelNode, findRow);
  524.  
  525.         var logRow = search.find(text);
  526.         if (!logRow)
  527.             return false;
  528.  
  529.         for (; logRow; logRow = search.findNext())
  530.         {
  531.             setClass(logRow, "matched");
  532.             this.matchSet.push(logRow);
  533.         }
  534.  
  535.         return true;
  536.     },
  537.  
  538.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  539.     // private
  540.  
  541.     createRow: function(rowName, className)
  542.     {
  543.         var elt = this.document.createElement("div");
  544.         elt.className = rowName + (className ? " " + rowName + "-" + className : "");
  545.         return elt;
  546.     },
  547.  
  548.     getTopContainer: function()
  549.     {
  550.         if (this.groups && this.groups.length)
  551.             return this.groups[this.groups.length-1];
  552.         else
  553.             return this.panelNode;
  554.     },
  555.  
  556.     filterLogRow: function(logRow, scrolledToBottom)
  557.     {
  558.         if (this.searchText)
  559.         {
  560.             setClass(logRow, "matching");
  561.             setClass(logRow, "matched");
  562.  
  563.             // Search after a delay because we must wait for a frame to be created for
  564.             // the new logRow so that the finder will be able to locate it
  565.             setTimeout(bindFixed(function()
  566.             {
  567.                 if (this.searchFilter(this.searchText, logRow))
  568.                     this.matchSet.push(logRow);
  569.                 else
  570.                     removeClass(logRow, "matched");
  571.  
  572.                 removeClass(logRow, "matching");
  573.  
  574.                 if (scrolledToBottom)
  575.                     scrollToBottom(this.panelNode);
  576.             }, this), 100);
  577.         }
  578.     },
  579.  
  580.     searchFilter: function(text, logRow)
  581.     {
  582.         var count = this.panelNode.childNodes.length;
  583.         var searchRange = this.document.createRange();
  584.         searchRange.setStart(this.panelNode, 0);
  585.         searchRange.setEnd(this.panelNode, count);
  586.  
  587.         var startPt = this.document.createRange();
  588.         startPt.setStartBefore(logRow);
  589.  
  590.         var endPt = this.document.createRange();
  591.         endPt.setStartAfter(logRow);
  592.  
  593.         return finder.Find(text, searchRange, startPt, endPt) != null;
  594.     },
  595.  
  596.     // nsIPrefObserver
  597.     observe: function(subject, topic, data)
  598.     {
  599.         // We're observing preferences only.
  600.         if (topic != "nsPref:changed")
  601.           return;
  602.  
  603.         // xxxHonza check this out.
  604.         var prefDomain = "Firebug.extension.";
  605.         var prefName = data.substr(prefDomain.length);
  606.         if (prefName == "console.logLimit")
  607.             this.updateMaxLimit();
  608.     },
  609.  
  610.     updateMaxLimit: function()
  611.     {
  612.         var value = Firebug.getPref(Firebug.prefDomain, "console.logLimit");
  613.         maxQueueRequests =  value ? value : maxQueueRequests;
  614.     }
  615. });
  616.  
  617. // ************************************************************************************************
  618.  
  619. function parseFormat(format)
  620. {
  621.     var parts = [];
  622.     if (format.length <= 0)
  623.         return parts;
  624.  
  625.     var reg = /((^%|.%)(\d+)?(\.)([a-zA-Z]))|((^%|.%)([a-zA-Z]))/;
  626.     for (var m = reg.exec(format); m; m = reg.exec(format))
  627.     {
  628.         if (m[0].substr(0, 2) == "%%")
  629.         {
  630.             parts.push(format.substr(0, m.index));
  631.             parts.push(m[0].substr(1));
  632.         }
  633.         else
  634.         {
  635.             var type = m[8] ? m[8] : m[5];
  636.             var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
  637.  
  638.             var rep = null;
  639.             switch (type)
  640.             {
  641.                 case "s":
  642.                     rep = FirebugReps.Text;
  643.                     break;
  644.                 case "f":
  645.                 case "i":
  646.                 case "d":
  647.                     rep = FirebugReps.Number;
  648.                     break;
  649.                 case "o":
  650.                     rep = null;
  651.                     break;
  652.             }
  653.  
  654.             parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
  655.             parts.push({rep: rep, precision: precision});
  656.         }
  657.  
  658.         format = format.substr(m.index+m[0].length);
  659.     }
  660.  
  661.     parts.push(format);
  662.  
  663.     return parts;
  664. }
  665.  
  666. // ************************************************************************************************
  667.  
  668. var appendObject = Firebug.ConsolePanel.prototype.appendObject;
  669. var appendFormatted = Firebug.ConsolePanel.prototype.appendFormatted;
  670. var appendOpenGroup = Firebug.ConsolePanel.prototype.appendOpenGroup;
  671. var appendCloseGroup = Firebug.ConsolePanel.prototype.appendCloseGroup;
  672.  
  673. // ************************************************************************************************
  674.  
  675. Firebug.registerActivableModule(Firebug.Console);
  676. Firebug.registerPanel(Firebug.ConsolePanel);
  677.  
  678. // ************************************************************************************************
  679.  
  680. }});
  681.